# character_loader.py
import json
import os
import importlib.util
import sqlite3
from typing import Any, Dict, List, Optional
from config import app_config  # 假设有一个配置文件，包含数据库路径等

CHARACTERS_DIR = os.path.join(os.path.dirname(__file__), "characters_cards")
LOADED_CHARACTERS: Dict[str, dict] = {}

def load_character_module_from_file(file_path: str):
    """动态导入角色文件"""
    
    # 1. 构造模块名
    module_name = f"characters_cards.{os.path.basename(file_path)[:-3]}"  # 去掉 .py
    
    # 2. 创建模块的“描述信息”
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    
    # 3. 检查是否成功创建描述
    if spec and spec.loader:
        # 4. 创建一个空的模块对象
        module = importlib.util.module_from_spec(spec)
        
        # 5. 执行模块中的代码（比如定义函数、变量）
        spec.loader.exec_module(module)
        
        # 6. 检查模块是否有 get_raw_character_data 函数
        if hasattr(module, "get_raw_character_data"):
            char_data = module.get_raw_character_data()  # 调用函数获取角色数据
            add_system_prompt(char_data)  # 添加 system_prompt
            LOADED_CHARACTERS[char_data["id"]] = char_data  # 存入全局字典
        else:
            print(f"⚠️ 跳过无效角色文件（缺少 get_raw_character_data）: {file_path}")
    else:
        print(f"⚠️ 无法加载模块: {file_path}")

def load_one_character_module_from_db(character_id: str) -> Optional[Dict[str, Any]]:
    """
    从 SQLite 数据库中读取角色数据，并还原为原始字典结构
    """
    conn = None
    try:
        conn = sqlite3.connect(app_config.sqlite_db_path)
        conn.row_factory = sqlite3.Row  # 返回字典风格
        cursor = conn.cursor()

        cursor.execute("""
        SELECT 
            id, name, faction, title,
            personality, speech_style, background, interaction_rules,
            catchphrases, behavior_patterns, prohibited, dialogue_examples,
            temperature, top_p,
            created_at, updated_at, enabled          
        FROM character_cards 
        WHERE id = ? AND deleted = 0
        """, (character_id,))

        row = cursor.fetchone()
        if not row:
            return {}

        # 转换为字典
        data = dict(row)

        # 反序列化 JSON 字段（列表类型）
        # json_fields = ['dialogue_examples','personality','speech_style','background','interaction_rules','catchphrases','behavior_patterns','prohibited']
        # for field in json_fields:
        #     try:
        #         data[field] = json.loads(data[field] or '[]')
        #     except (json.JSONDecodeError, TypeError):
        #         data[field] = []

        # interaction_rules 是字符串，无需解析
        # temperature / top_p 是数值，直接使用
        add_system_prompt(data)
        return data

    except Exception as e:
        print(f"❌ 读取角色卡失败: {e}")
        return None
    finally:
        if conn:
            conn.close()

# def load_all_characters():
#     """扫描 charaters_cards 目录，加载所有角色"""
#     # 声明函数外部的全局变量
#     global LOADED_CHARACTERS
#     LOADED_CHARACTERS.clear()

#     # 先从数据库加载
#     LOADED_CHARACTERS.update(load_character_module_from_db() or {})
#     # 再从本地文件加载
#     if not os.path.exists(CHARACTERS_DIR):
#         print(f"❌ 角色目录不存在: {CHARACTERS_DIR}")
#         return

#     for filename in os.listdir(CHARACTERS_DIR):
#         if filename.endswith(".py") and not filename.startswith("__"):
#             file_path = os.path.join(CHARACTERS_DIR, filename)
#             load_character_module_from_file(file_path)

#     print(f"✅ 成功从本地文件中加载 {len(LOADED_CHARACTERS)} 个角色")


def load_character_module_from_db(name,faction,enabled) -> List[Dict[str, Any]]:
    """
    从 SQLite 数据库中读取角色数据，并还原为原始字典结构
    """
    conn = None
    new_characters = []
    try:
        conn = sqlite3.connect(app_config.sqlite_db_path)
        conn.row_factory = sqlite3.Row  # 返回字典风格
        cursor = conn.cursor()

       # 基础SQL
        sql = """
        SELECT 
            id, name, faction, title,
            personality, speech_style, background, interaction_rules,
            catchphrases, behavior_patterns, prohibited, dialogue_examples,
            temperature, top_p,
            created_at, updated_at, enabled
        FROM character_cards
        WHERE deleted = 0
        """
        params = []

        # 动态拼接条件
        if name:
            sql += " AND name LIKE ?"
            params.append(f"%{name}%")
        if faction:
            sql += " AND faction LIKE ?"
            params.append(f"%{faction}%")
        if enabled is not None:
            sql += " AND enabled = ?"
            params.append(enabled)

        cursor.execute(sql, params)
        rows = cursor.fetchall()

        if not rows:
            print("🟡 警告：数据库中未找到任何启用的角色卡。")
            return []
        for row in rows:
            # 转换为字典
            data = dict(row)

            # 反序列化 JSON 字段（列表类型）
            # json_fields = ['dialogue_examples','personality','speech_style','background','interaction_rules','catchphrases','behavior_patterns','prohibited']
            # for field in json_fields:
            #     try:
            #         data[field] = json.loads(data[field] or '[]')
            #     except (json.JSONDecodeError, TypeError):
            #         data[field] = []
            
            add_system_prompt(data)
            new_characters.append(data)  # 添加 system_prompt 并存入全局字典
        # interaction_rules 是字符串，无需解析
        # temperature / top_p 是数值，直接使用

        return new_characters

    except Exception as e:
        print(f"❌ 读取角色卡失败: {e}")
        return []
    finally:
        if conn:
            conn.close()

def get_character(character_id: str) -> dict:
    """获取指定角色数据"""
    return LOADED_CHARACTERS.get(character_id) # type: ignore

def list_characters() -> List[dict]:
    """列出所有已加载角色（精简信息）"""
    return [
        {
            "id": c["id"],
            "name": c["name"],
            "title": c["title"],
            "faction": c["faction"],
            "personality": c["personality"],
        }
        for c in LOADED_CHARACTERS.values()
    ]


def _build_system_prompt(c) -> str:
    """根据角色信息动态生成最终的 system prompt"""

    prompt = f"""
你正在精准扮演角色「{c['name']}」。请严格遵循以下设定进行互动：

【身份设定】
{c['title']}，隶属于 {c['faction']}

【性格特质】
{c['personality']}

【语言风格】
{c['speech_style']}

【标志性表达】
{c['catchphrases']}

【背景设定】
{c['background']}

【行为模式】
{c['behavior_patterns']}

【禁止事项】
{c['prohibited']}

【对话示例】
{c['dialogue_examples']}

【当前互动规则】
{c['interaction_rules']}
    """

    return prompt.strip()


def _build_system_prompt_v1(c) -> str:
    """根据角色信息动态生成最终的 system prompt"""
    
    # 辅助函数：将列表转换为带序号的条目
    def format_list(items, prefix="- "):
        return "\n".join([f"{prefix}{item}" for item in items])
    
    # 格式化对话示例
    dialogue_examples = []
    for example in c["dialogue_examples"]:
        dialogue_examples.append(f"{example['speaker']}: {example['speech']}")
    formatted_dialogues = "\n".join(dialogue_examples)

    prompt = f"""
你正在精准扮演角色「{c['name']}」。请严格遵循以下设定进行互动：

【身份设定】
{c['title']}，隶属于 {c['faction']}

【性格特质】
{format_list(c['personality'])}

【语言风格】
{format_list(c['speech_style'])}

【标志性表达】
{format_list(c['catchphrases'], prefix="· ")}

【背景设定】
{format_list(c['background'], prefix="")}  

【行为模式】
{format_list(c['behavior_patterns'])}

【禁止事项】
{format_list(c['prohibited'], prefix="❌ ")}

【对话示例】
{formatted_dialogues}

【当前互动规则】
{format_list(c['interaction_rules'], prefix="⚠️ ")}
    """

    return prompt.strip()

def add_system_prompt(data):
    data["system_prompt"] = _build_system_prompt(data)


# 启动时自动加载
# 暂未找到兼容的办法，先弃用这里
# load_all_characters()


